package com.sikulifang.bank.simulation.service.bank;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.sql.SqlBuilder;
import com.sikulifang.bank.simulation.constant.CodeConstants;
import com.sikulifang.bank.simulation.dto.QueryReceiptDTO;
import com.sikulifang.bank.simulation.dto.ReceiptDTO;
import com.sikulifang.bank.simulation.dto.ResponseReceiptDTO;
import com.sikulifang.bank.simulation.enums.BankEnum;
import com.sikulifang.bank.simulation.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;

import javax.xml.xpath.XPathConstants;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.List;

import static com.sikulifang.bank.simulation.constant.TableConstants.DETAIL_TABLE_NAME;

/**
 * ClassName CEBBBankMessage
 * Description 光大银行
 *
 * @author Yat
 * Date 2023年6月12日, 0012 11:40
 * version 1.0
 */
@Slf4j
@Service
public class CEBBBankMessage extends AbstractBankMessage {


    @Override
    protected String getType(String actionName) {
        return null;
    }

    @Override
    public String getActionName(String message) {
        Document document = XmlUtil.readXML(message);
        return Convert.toStr(
                XmlUtil.getByXPath("//Transaction/TransHead/TransCode", document, XPathConstants.STRING)
        );
    }

    @Override
    public String inlet(String message) {

        Document document = XmlUtil.readXML(message);
        String action = Convert.toStr(
                XmlUtil.getByXPath("//Transaction/TransHead/TransCode", document, XPathConstants.STRING)
        );

        if (StrUtil.equals(action, "b2e005003")) {
            return queryReceiptInfo(document);
        } else {
            return error("0104", "无此交易类型！");
        }

    }

    private String error(String code, String msg) {
        return "<?xml version=\"1.0\" encoding=\"GBK\"?>" +
               "<Transaction>" +
               "<ReturnCode>" + code + "</RetrunCode>" +
               "<ReturnMsg>" + msg + "<ReturnMsg>" +
               "<error>com.csii.pe.core.PeRuntimeException MessageCode: invalid_char Args: </error>" +
               "</Transaction>";
    }

    private String queryReceiptInfo(Document document) {

        String acNo = Convert.toStr(
                XmlUtil.getByXPath("//Transaction/TransContent/ReqData/ActNo", document, XPathConstants.STRING)
        );
        String beginDate = Convert.toStr(
                XmlUtil.getByXPath("//Transaction/TransContent/ReqData/BeginDate", document, XPathConstants.STRING)
        );
        String endDate = Convert.toStr(
                XmlUtil.getByXPath("//Transaction/TransContent/ReqData/EndDate", document, XPathConstants.STRING)
        );
        int reqPage = Convert.toInt(
                XmlUtil.getByXPath("//Transaction/TransContent/ReqData/BeginNum", document, XPathConstants.NUMBER)
        );
        int reqNum = Convert.toInt(
                XmlUtil.getByXPath("//Transaction/TransContent/ReqData/QueryNum", document, XPathConstants.NUMBER)
        );
        int BatchID = Convert.toInt(
                XmlUtil.getByXPath("//Transaction/TransHead/BatchID", document, XPathConstants.NUMBER)
        );


        QueryReceiptDTO queryReceipt = new QueryReceiptDTO();
        queryReceipt.setStartDate(beginDate);
        queryReceipt.setEndDate(endDate);
        queryReceipt.setAccNo(acNo);
        queryReceipt.setSize(reqNum);
        queryReceipt.setReqPage(reqPage);

        R<ResponseReceiptDTO> dictR = queryReceipt(queryReceipt);
        if (dictR.getCode() != CodeConstants.SUCCESS) {
            return error("ETB4000", "交易未成功");
        }

        int TotalNum = dictR.getData().getTotalPage();

        StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"GBK\"?>")
                .append("<Transaction>")
                .append("    <SystemHead>")
                .append("        <Language>zh_CN</Language>")
                .append("        <Encodeing></Encodeing>")
                .append("        <Version></Version>")
                .append("        <ServiceName></ServiceName>")
                .append("        <CifNo>0000003068</CifNo>")
                .append("        <UserId>001</UserId>")
                .append("        <SyMacFlag></SyMacFlag>")
                .append("        <MAC></MAC>")
                .append("        <SyPinFlag></SyPinFlag>")
                .append("        <PinSeed></PinSeed>")
                .append("        <LicenseId></LicenseId>")
                .append("        <Flag></Flag>")
                .append("        <Note></Note>")
                .append("    </SystemHead>")
                .append("    <TransHead>")
                .append("        <TransCode>b2e005003</TransCode>")
                .append("        <BatchID>").append(BatchID).append("</BatchID>")
                .append("        <JnlDate>2010-08-11</JnlDate>")
                .append("        <JnlTime></JnlTime>")
                .append("        <response1></response1>")
                .append("        <response2></response2>")
                .append("        <response3></response3>")
                .append("    </TransHead>")
                .append("    <TransContent>")
                .append("        <ReturnCode></ReturnCode>")
                .append("        <ReturnMsg></ReturnMsg>")
                .append("        <ReturnNote></ReturnNote>")
                .append("        <TotalNum>").append(TotalNum).append("</TotalNum>")
                .append("        <BatchRespList>");

        List<Entity> listData = dictR.getData().getData();

        for (Entity obj : listData) {

            // 收款人
            String AcName2;
            String AcBankName2;
            String AcNo2;

            // 付款人
            String AcName;
            String AcBankName;
            String AcNo;

            if ("D".equals(obj.getStr("flag"))) {
                AcName = obj.getStr("account_name");
                AcBankName = obj.getStr("bank_name");
                AcNo = obj.getStr("account_no");

                AcName2 = obj.getStr("opp_account_name");
                AcBankName2 = obj.getStr("opp_bank_name");
                AcNo2 = obj.getStr("opp_account_no");
            } else {
                AcName2 = obj.getStr("account_name");
                AcBankName2 = obj.getStr("bank_name");
                AcNo2 = obj.getStr("account_no");

                AcName = obj.getStr("opp_account_name");
                AcBankName = obj.getStr("opp_bank_name");
                AcNo = obj.getStr("opp_account_no");
            }

            xml.append("<RespData>")
                    .append("  <BillNumber>").append(BatchID).append("</BillNumber>")
                    .append("  <WriteDate>").append(obj.getStr("tran_date")).append("</WriteDate>")
                    .append("  <AcName2>").append(AcName2).append("</AcName2>")
                    .append("  <AcBankName2>").append(AcBankName2).append("</AcBankName2>")
                    .append("  <AcNo2>").append(AcNo2).append("</AcNo2>")
                    .append("  <AcName>").append(AcName).append("</AcName>")
                    .append("  <AcNo>").append(AcNo).append("</AcNo>")
                    .append("  <AcBankName>").append(AcBankName).append("</AcBankName>")
                    .append("  <Amount>").append(obj.getBigDecimal("money")).append("</Amount>")
                    .append("  <purpose>").append(obj.getStr("use_cn")).append("</purpose>")
                    .append("  <FlowNumber>").append(obj.getStr("batch_serial_no")).append("</FlowNumber>")
                    .append("  <ValidateCode>E0434EB45862FA82</ValidateCode>")
                    .append("  <BillQueryCode>").append(obj.getStr("id")).append("</BillQueryCode>")
                    .append("  <respond1></respond1>")
                    .append("  <respond2></respond2>")
                    .append("  <respond3></respond3>")
                    .append("  <respond4></respond4>")
                    .append("  <respond5></respond5>")
                    .append("</RespData>");
        }

        return xml + "</BatchRespList></TransContent><Transaction>";
    }

    @Override
    public String bankCode() {
        return BankEnum.CEBB.name();
    }

    @Override
    public R<Dict> dowReceipt(List<ReceiptDTO> receiptList) {
        return null;
    }

    /**
     * 查询电子回单
     *
     * @param queryReceipt 查询电子回单的参数
     */
    private R<ResponseReceiptDTO> queryReceipt(QueryReceiptDTO queryReceipt) {
        ResponseReceiptDTO dto = new ResponseReceiptDTO();

        // 账号
        String accNo = queryReceipt.getAccNo();

        BigDecimal maxAmt = queryReceipt.getMaxAmt();
        BigDecimal minAmt = queryReceipt.getMinAmt();

        String startDate = queryReceipt.getStartDate();
        String endDate = queryReceipt.getEndDate();

        // 起始
        int reqPage = queryReceipt.getReqPage();
        int size = queryReceipt.getSize();

        if (size > 50) {
            return R.failed(dto, "最多每次查50笔");
        }

        try {
            SqlBuilder builder = getWrapper(accNo, maxAmt, minAmt, startDate, endDate);
            long number = db.count(builder.build());
            int count = Convert.toInt(number);

            builder.append(" limit " + reqPage + " , " + size);
            List<Entity> query = db.query(builder.build());

            dto.setData(query);
            dto.setTotalPage(count);
            return R.ok(dto);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }

    private SqlBuilder getWrapper(String accNo, BigDecimal maxAmt, BigDecimal minAmt, String startDate,
                                  String endDate) {

        SqlBuilder builder = SqlBuilder.create().select("*").from(DETAIL_TABLE_NAME)
                .where("status = 1")
                .append(" and account_no = '" + accNo + "'")
                .append(" and bank_code = '" + bankCode() + "'");

        if (ObjectUtil.isNotNull(minAmt)) {
            builder.append(" and money >= " + minAmt);
        }
        if (ObjectUtil.isNotNull(maxAmt)) {
            builder.append(" and money <= " + maxAmt);
        }

        if (CharSequenceUtil.isNotBlank(startDate)) {
            builder.append(" and tran_date >= '" + startDate + "'");
        }
        if (CharSequenceUtil.isNotBlank(endDate)) {
            builder.append(" and tran_date <= '" + endDate + "'");
        }


        return builder;
    }
}
